package com.vibrationkeyboard.app.processor

import com.vibrationkeyboard.app.model.SensorData
import kotlin.math.*

class SignalProcessor {
    
    private val dataBuffer = mutableListOf<SensorData>()
    private val maxBufferSize = 1000 // 10秒的数据 (100Hz * 10s)
    private var latestRecognitionResult: String? = null
    
    // 端点检测参数
    private val energyThresholdHigh = 0.8f
    private val energyThresholdLow = 0.3f
    private val zeroCrossingThreshold = 0.5f
    private val minSilenceLength = 0.1f // 秒
    private val minSpeechLength = 0.05f // 秒
    
    // 特征提取参数
    private val frameLength = 256
    private val frameShift = 128
    
    fun processSensorData(data: List<SensorData>) {
        // 添加数据到缓冲区
        dataBuffer.addAll(data)
        
        // 保持缓冲区大小
        if (dataBuffer.size > maxBufferSize) {
            dataBuffer.removeAt(0)
        }
        
        // 检测震动事件
        val vibrationEvent = detectVibrationEvent()
        if (vibrationEvent != null) {
            // 提取特征
            val features = extractFeatures(vibrationEvent)
            
            // 进行键位识别
            val recognitionResult = recognizeKey(features)
            latestRecognitionResult = recognitionResult
        }
    }
    
    fun getLatestRecognitionResult(): String? {
        return latestRecognitionResult
    }
    
    private fun detectVibrationEvent(): List<SensorData>? {
        if (dataBuffer.size < 50) return null // 至少需要0.5秒的数据
        
        // 计算短时能量
        val energy = calculateShortTimeEnergy(dataBuffer)
        
        // 计算过零率
        val zeroCrossingRate = calculateZeroCrossingRate(dataBuffer)
        
        // 双阈值端点检测
        val startIndex = findStartPoint(energy, zeroCrossingRate)
        val endIndex = findEndPoint(energy, zeroCrossingRate, startIndex)
        
        if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) {
            val eventLength = (endIndex - startIndex) / 100f // 转换为秒
            if (eventLength >= minSpeechLength) {
                return dataBuffer.subList(startIndex, endIndex)
            }
        }
        
        return null
    }
    
    private fun calculateShortTimeEnergy(data: List<SensorData>): List<Float> {
        val energy = mutableListOf<Float>()
        val windowSize = 20 // 200ms窗口
        
        for (i in 0 until data.size - windowSize) {
            var sum = 0f
            for (j in 0 until windowSize) {
                val magnitude = data[i + j].magnitude
                sum += magnitude * magnitude
            }
            energy.add(sum / windowSize)
        }
        
        return energy
    }
    
    private fun calculateZeroCrossingRate(data: List<SensorData>): List<Float> {
        val zeroCrossingRate = mutableListOf<Float>()
        val windowSize = 20
        
        for (i in 0 until data.size - windowSize) {
            var crossings = 0
            for (j in 1 until windowSize) {
                val prev = data[i + j - 1].magnitude
                val curr = data[i + j].magnitude
                if ((prev > 0 && curr <= 0) || (prev < 0 && curr >= 0)) {
                    crossings++
                }
            }
            zeroCrossingRate.add(crossings.toFloat() / windowSize)
        }
        
        return zeroCrossingRate
    }
    
    private fun findStartPoint(energy: List<Float>, zeroCrossingRate: List<Float>): Int {
        val minLength = (minSilenceLength * 100).toInt() // 转换为采样点数
        
        for (i in minLength until energy.size) {
            val avgEnergy = energy.subList(i - minLength, i).average().toFloat()
            val avgZeroCrossing = zeroCrossingRate.subList(i - minLength, i).average().toFloat()
            
            if (avgEnergy > energyThresholdHigh && avgZeroCrossing > zeroCrossingThreshold) {
                return i
            }
        }
        
        return -1
    }
    
    private fun findEndPoint(energy: List<Float>, zeroCrossingRate: List<Float>, startIndex: Int): Int {
        val minLength = (minSilenceLength * 100).toInt()
        
        for (i in startIndex + minLength until energy.size) {
            val avgEnergy = energy.subList(i - minLength, i).average().toFloat()
            val avgZeroCrossing = zeroCrossingRate.subList(i - minLength, i).average().toFloat()
            
            if (avgEnergy < energyThresholdLow && avgZeroCrossing < zeroCrossingThreshold) {
                return i
            }
        }
        
        return energy.size - 1
    }
    
    private fun extractFeatures(vibrationEvent: List<SensorData>): Map<String, Float> {
        val features = mutableMapOf<String, Float>()
        
        // 时域特征
        features["amplitude"] = extractAmplitude(vibrationEvent)
        features["energy"] = extractEnergy(vibrationEvent)
        features["zero_crossing_rate"] = extractZeroCrossingRate(vibrationEvent)
        features["rms"] = extractRMS(vibrationEvent)
        features["peak_to_peak"] = extractPeakToPeak(vibrationEvent)
        
        // 频域特征
        val fftFeatures = extractFrequencyFeatures(vibrationEvent)
        features.putAll(fftFeatures)
        
        return features
    }
    
    private fun extractAmplitude(data: List<SensorData>): Float {
        return data.maxOfOrNull { it.magnitude } ?: 0f
    }
    
    private fun extractEnergy(data: List<SensorData>): Float {
        return data.sumOf { (it.magnitude * it.magnitude).toDouble() }.toFloat()
    }
    
    private fun extractZeroCrossingRate(data: List<SensorData>): Float {
        var crossings = 0
        for (i in 1 until data.size) {
            val prev = data[i - 1].magnitude
            val curr = data[i].magnitude
            if ((prev > 0 && curr <= 0) || (prev < 0 && curr >= 0)) {
                crossings++
            }
        }
        return crossings.toFloat() / data.size
    }
    
    private fun extractRMS(data: List<SensorData>): Float {
        val sum = data.sumOf { (it.magnitude * it.magnitude).toDouble() }
        return sqrt(sum / data.size).toFloat()
    }
    
    private fun extractPeakToPeak(data: List<SensorData>): Float {
        val max = data.maxOfOrNull { it.magnitude } ?: 0f
        val min = data.minOfOrNull { it.magnitude } ?: 0f
        return max - min
    }
    
    private fun extractFrequencyFeatures(data: List<SensorData>): Map<String, Float> {
        val features = mutableMapOf<String, Float>()
        
        // 简单的FFT实现（这里使用简化版本）
        val magnitudes = data.map { it.magnitude }
        val fft = performFFT(magnitudes)
        
        // 功率谱密度
        features["power_spectral_density"] = calculatePowerSpectralDensity(fft)
        
        // 谱质心
        features["spectral_centroid"] = calculateSpectralCentroid(fft)
        
        // 谱滚降
        features["spectral_rolloff"] = calculateSpectralRolloff(fft)
        
        return features
    }
    
    private fun performFFT(data: List<Float>): List<Complex> {
        // 简化的FFT实现
        val n = data.size
        val fft = mutableListOf<Complex>()
        
        for (k in 0 until n) {
            var real = 0.0
            var imag = 0.0
            
            for (j in 0 until n) {
                val angle = -2.0 * PI * k * j / n
                real += data[j] * cos(angle)
                imag += data[j] * sin(angle)
            }
            
            fft.add(Complex(real, imag))
        }
        
        return fft
    }
    
    private fun calculatePowerSpectralDensity(fft: List<Complex>): Float {
        return fft.sumOf { (it.real * it.real + it.imag * it.imag).toDouble() }.toFloat() / fft.size
    }
    
    private fun calculateSpectralCentroid(fft: List<Complex>): Float {
        var weightedSum = 0.0
        var totalPower = 0.0
        
        for (i in fft.indices) {
            val power = fft[i].real * fft[i].real + fft[i].imag * fft[i].imag
            weightedSum += i * power
            totalPower += power
        }
        
        return if (totalPower > 0) (weightedSum / totalPower).toFloat() else 0f
    }
    
    private fun calculateSpectralRolloff(fft: List<Complex>): Float {
        val totalPower = fft.sumOf { (it.real * it.real + it.imag * it.imag).toDouble() }
        val threshold = totalPower * 0.85 // 85%的能量
        
        var cumulativePower = 0.0
        for (i in fft.indices) {
            val power = fft[i].real * fft[i].real + fft[i].imag * fft[i].imag
            cumulativePower += power
            if (cumulativePower >= threshold) {
                return i.toFloat() / fft.size
            }
        }
        
        return 1.0f
    }
    
    private fun recognizeKey(features: Map<String, Float>): String {
        // 简化的键位识别算法
        // 这里使用基于特征阈值的简单分类
        
        val amplitude = features["amplitude"] ?: 0f
        val energy = features["energy"] ?: 0f
        val zeroCrossingRate = features["zero_crossing_rate"] ?: 0f
        
        // 基于振幅和能量的简单分类
        return when {
            amplitude > 15f && energy > 1000f -> "A"
            amplitude > 12f && energy > 800f -> "B"
            amplitude > 10f && energy > 600f -> "C"
            amplitude > 8f && energy > 400f -> "D"
            amplitude > 6f && energy > 200f -> "E"
            else -> "未知"
        }
    }
    
    private data class Complex(val real: Double, val imag: Double)
} 